<!-- 裁剪图片弹窗组件 -->
<template>
  <el-dialog
    :title="title"
    :visible.sync="open"
    center
    width="850px"
    append-to-body
    :before-close="
      () => {
        open = false;
      }
    "
  >
    <div class="disFlx">
      <div style="width: 400px; height: 400px">
        <vue-cropper
          v-if="visible"
          ref="cropper"
          :img="options.img"
          :info="true"
          :autoCrop="options.autoCrop"
          :autoCropWidth="width"
          :autoCropHeight="height"
          :fixed="options.fixed"
          :fixedNumber="options.fixedNumber"
          fillColor="#FFFFFF"
          @realTime="realTime"
        />
      </div>
      <div
        style="width: 400px; height: 400px; background-color: #fafafa"
        class="disFlxCC"
      >
        <div
          class="imgUploadPreview"
          :style="`width:${previews.w || width}px;height:${
            previews.h || height
          }px;border-radius:${borderRadius};`"
        >
          <img :src="previews.url" :style="previews.img" />
        </div>
      </div>
    </div>

    <div class="disFlxJS mt-20">
      <div class="disFlxAC">
        <el-upload
          :accept="fileType.join(',')"
          action="#"
          :showUploadList="false"
          :before-upload="beforeUpload"
        >
          <el-button icon="el-icon-upload">选择图片</el-button>
        </el-upload>

        <el-button
          icon="el-icon-plus"
          class="ml-10"
          @click="changeScale(1)"
        ></el-button>
        <el-button
          icon="el-icon-minus"
          class="ml-10"
          @click="changeScale(-1)"
        ></el-button>
        <el-button
          icon="el-icon-refresh-left"
          class="ml-10"
          @click="rotateLeft()"
        ></el-button>
        <el-button
          icon="el-icon-refresh-right"
          class="ml-10"
          @click="rotateRight()"
        ></el-button>
      </div>

      <el-button type="primary" :loading="loading" @click="uploadImg()"
        >提 交</el-button
      >
    </div>
  </el-dialog>
</template>

<script>
// https://github.com/xyxiao001/vue-cropper
import { VueCropper } from "vue-cropper";
import { customUpFile } from "@/api/upload";

export default {
  components: { VueCropper },
  props: {
    // 上传类型范围 例如['.png', '.jpg', '.jpeg'] || ['.mp4']
    fileType: {
      type: Array,
      default: () => [".png", ".jpg", ".jpeg"],
    },
    // 图片大小限制 M
    fileSize: {
      type: Number,
      default: 5,
    },
    // 图片宽度
    width: {
      type: Number,
      default: 148,
    },
    // 图片高度
    height: {
      type: Number,
      default: 148,
    },
    // 圆角
    borderRadius: {
      type: String,
      default: "",
    },
  },
  mounted() {
    this.options.fixedNumber = [this.width / this.height, 1];
  },
  watch: {
    width(val) {
      this.options.fixedNumber = [val / this.height, 1];
    },
    height(val) {
      this.options.fixedNumber = [this.width / val, 1];
    },
  },
  data() {
    return {
      open: false,
      // 是否显示cropper
      visible: false,
      // 弹出层标题
      title: "裁剪图片",
      options: {
        img: "", //裁剪图片的地址
        autoCrop: true, // 是否默认生成截图框
        // fixedBox: true, // 不允许改变截图框大小
        fixed: true, // 是否允许等比缩放
        fixedNumber: [1, 1], // 等比缩放比例 [宽度, 高度]
      },
      previews: {},
      loading: false,
    };
  },
  methods: {
    // url 默认裁剪图片
    show(url) {
      this.open = true;
      this.$nextTick(() => {
        this.visible = true;
        this.options.img = url ? url + "?time=" + Date.parse(new Date()) : "";
      });
    },
    // 向左旋转
    rotateLeft() {
      this.$refs.cropper.rotateLeft();
    },
    // 向右旋转
    rotateRight() {
      this.$refs.cropper.rotateRight();
    },
    // 图片缩放
    changeScale(num) {
      num = num || 1;
      this.$refs.cropper.changeScale(num);
    },
    // 上传预处理
    beforeUpload(file) {
      const upfileScope = this.fileType.map(
        (v) => "image/" + v.replace(".", "")
      );
      const isImgType = upfileScope.includes(file.type);
      if (!isImgType) {
        this.$message.error(`请上传${this.fileType.join(" ")}格式的图片!`);
        return false;
      }
      const isImgSize = file.size / 1024 / 1024 < this.fileSize;
      if (!isImgSize) {
        this.$message.error(`图片大小不能超过${this.fileSize}M!`);
        return false;
      }
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => {
        this.options.img = reader.result;
      };
    },
    // 上传图片
    uploadImg() {
      const that = this;
      that.loading = true;
      try {
        that.$refs.cropper.getCropBlob((data) => {
          // blob转为file
          const files = new window.File(
            [data],
            `${Date.parse(new Date())}_cropper_${data.type.replace("/", ".")}`,
            { type: data.type }
          );
          const formData = new FormData();
          formData.append("file", files);
          customUpFile(formData).then((res) => {
            that.$emit("success", res.url);
            that.open = false;
            that.visible = false;
          }).finally(() => {
            that.loading = false;
          })
        });
      } catch (err) {
        this.loading = false;
      }
    },
    // 实时预览
    realTime(data) {
      this.previews = data;
    },
  },
};
</script>
<style scoped lang="scss">
.imgUploadPreview {
  box-shadow: 0 0 4px #ccc;
  overflow: hidden;
}
</style>
